﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Threading;
using System.Text.RegularExpressions;
using System.Drawing;

namespace MIBETerminal
{
    public class SerialPortService
    {
        bool _continue;
        SerialPort _serialPort;
        Thread readThread;
        private List<string> logBuffer;
        List<FilteredLog> filteredLogs;
        List<Filter> filters;
        public ManualResetEvent NewData { get; set; }
        public event EventHandler NewDataDelegate;

        protected virtual void OnNewDataDelegate(EventArgs e)
        {
            if (NewDataDelegate != null)
                NewDataDelegate(this, e);
        }
        
        public SerialPortService()
        {
            logBuffer = new List<string>();
            filters = new List<Filter>();
            _serialPort = new SerialPort();
            _serialPort.ReadTimeout = 500;
            _serialPort.WriteTimeout = 500;
        }

        public void addFilter(Filter newFilter)
        {
            filters.Add(newFilter);
        }

        public List<FilteredLog> getFilteredLogs()
        {
            filteredLogs = new List<FilteredLog>();
            //List<string> logBufferCopy = logBuffer.
            List<FilteredLog> filteredLogs2;
            lock (logBuffer)
            {
                filteredLogs2 = logBuffer.ConvertAll(new Converter<string, FilteredLog>(LogConverted));
            }
            return filteredLogs2;
        }

        public static FilteredLog LogConverted(string logMessage)
        {
            return new FilteredLog(logMessage, Color.Black);
        }

        public void setupSerialPort(SerialPortParameters serialPortParameters)
        {
            _serialPort.PortName = serialPortParameters.PortName ;
            _serialPort.BaudRate = serialPortParameters.BaudRate();
            _serialPort.DataBits = serialPortParameters.DataBits();
            _serialPort.Parity = serialPortParameters.Parity();
            _serialPort.StopBits = serialPortParameters.StopBits();
            _serialPort.Handshake = serialPortParameters.Handshake();
        }

        public void WriteLine(string message)
        {
            _serialPort.WriteLine(message);
        }

        public void Connect()
        {
            _continue = true;
            readThread = new Thread(ReadLoop);
            _serialPort.Open();
            readThread.Start();
        }
        public void Disconnect()
        {
            _continue = false;
            _serialPort.Close();
            readThread.Join();
        }

        public SerialPort getSerialPortObject()
        {
            return _serialPort;
        }

        public static List<string> GetBaudrates()
        {
            List<string> baudrates = new List<string>();
            baudrates.Add("9600");
            baudrates.Add("38400");
            baudrates.Add("57600");
            baudrates.Add("115200");
            return baudrates;
        }

        public void ReadLoop()
        {
            
            while (_continue)
            {
                try
                {
                    string message = _serialPort.ReadLine();
                    lock (logBuffer)
                    {
                        logBuffer.Add(message);
                    }
                    Console.WriteLine(message);
                    NewData.Set();
                }
                catch (TimeoutException) { }
            }
        }

        #region Serial Port Parameter Getters
        public static List<string> GetParity()
        {
            return Enum.GetNames(typeof(Parity)).ToList();
        }

        public static List<string> GetStopBits()
        {
            return Enum.GetNames(typeof(StopBits)).ToList();
        }

        public static List<string> GetHandshake()
        {
            return Enum.GetNames(typeof(Handshake)).ToList();
        }
        #endregion

        public List<string> getCopyOfLogBuffer()
        {
            List<string> copyOfLogBuffer = new List<string>() ;
            lock (logBuffer)
            {
                //Converter<string, string> convDelegate = delegate(string s) { return (string)s.Clone(); };
                Converter<string, string> convDelegate = (s) => { return String.Copy(s); };

                copyOfLogBuffer = logBuffer.ConvertAll(convDelegate);

                //foreach ( string s in logbuffer )
                //{
                //    copyoflogbuffer.add((string)s.clone());
                //}
            }
            return copyOfLogBuffer;
        }
    }

}
